package chapter2_nio.obj;

import java.io.Serializable;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class SenderUtil {
    int stepIndex;//用于计数数据帧。发送一次或接收一次，stepIndex就+1(receiverUtil和SenderUtil会根据之前的StepIndex的值+1)
    //客户端的一组receiverUtil和SenderUtil， 每次操作会根据之前的receiverUtil.StepIndex或SenderUtil.StepIndex的值+1
    //客户端的最终的SenderUtil.StepIndex为3证明客户端的四个数据操作都完毕了，就可以关闭客户端的SocketChannel

    //服务端的一组receiverUtil和SenderUtil， 每次操作会根据之前的receiverUtil.StepIndex或SenderUtil.StepIndex的值+1
    //服务端的最终的receiverUtil.StepIndex为3证明服务端的四个数据操作都完毕了，就可以关闭本次操作的客户端的SocketChannel
    ByteBuffer buffer;//用于存储对象数据(String对象或者普通java对象或者文件对象)
    ByteBuffer countBuffer;//用于存储对象的字节数(数据帧的字节数)
    boolean isCountDone = false;//用于判断是否将ByteBuffer countBuffer存储的对象的长度发送完毕

    Object obj;//要发送的对象(需要转为ByteBuffer赋值给buffer成员变量)


    public int getStepIndex() {//√ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √
        return stepIndex;
    }

    Object getObject(){//√ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √
        return obj;
    }


    /** i用于给stepIndex赋值，object用于给obj成员变量赋值 */
    SenderUtil(int i, Object object)throws  Exception{//√ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √
        this.obj=object;
        //对象转为ByteBuffer
        buffer=objToByteBuffer(obj);//buffer用于存储对象数据(String对象或者普通java对象或者文件对象)
        countBuffer=ByteBuffer.allocate(4);//countBuffer用于存储要发送的对象的字节数(数据帧的字节数)
        countBuffer.putInt(0, buffer.capacity());//将对象的字节数存储到countBuffer
        stepIndex=i;
    }

    ByteBuffer objToByteBuffer(Object object)throws  Exception{
        //字符串对象序列化为ByteBuffer(String对象和其他对象转byte数组的方式不一样)
        if(object instanceof  String){
            String str=(String)object;
            //先用str.getBytes("UTF-8")将字符串变为byte数组，再用wrap将byte数组变为ByteBuffer
            return ByteBuffer.wrap( str.getBytes("UTF-8") );
        }
        if(object instanceof Serializable){
            return ByteBuffer.wrap(NIOSendReceiveUtil_6.objSerializableToByteArray(object));
        }
        throw new Exception("对象没有实现序列化接口，无法将object转化为ByteBuffer");
    }

    boolean sendFully(SocketChannel channel)throws  Exception{//√ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √ √
        //注意：此方法会无限循环调用(在Server类的service()方法中循环调用session方法(session方法又调用sendFully方法))
        //(还有Client类的communicate()方法中循环调用session方法(session方法又调用sendFully方法))
        //所以可能会多次执行channel.write(countBuffer);将countBuffer中要发送的对象的长度数据写出到channel中
        //(长度发送完后再多次发送buffer中的对象数据到channel中)
        // !false 表示isCountDown为false，表示ByteBuffer buffer中存储的对象数据没有发送完毕(就用下边代码发送)
        if(!isCountDone){
            channel.write(countBuffer);//发送对象长度数据(一个数据帧)
            System.out.println(countBuffer.getInt(0)+"发送长度");
            //判断对象长度数据是否发送完毕(如果还有未发送的数据 则isCountDone为  !true)
            isCountDone=!countBuffer.hasRemaining();
            return  false;//返回false表示数据没发送完毕(ByteBuffer countBuffer中存储的对象长度数据)
        }else{
            System.out.println(countBuffer.getInt(0)+"发送长度222");
            channel.write(buffer);//发送ByteBuffer buffer中存储的对象数据(一个数据帧)
            //判断ByteBuffer buffer中存储的对象数据是否发送完毕(如果还有未发送的数据 则isCountDone为  !true)
            return  !buffer.hasRemaining();
            //注意：此方法会无限循环调用(在Server类的service()方法中循环调用session方法(session方法又调用sendFully方法))
            //(还有Client类的communicate()方法中循环调用session方法(session方法又调用sendFully方法))
            //所以可能会多次执行channel.write(buffer);将buffer中要发送的对象数据写出到channel中
        }
    }

    /*boolean sendBufferFully(SocketChannel channel, ByteBuffer countBuffer)throws  Exception{
        channel.write(buffer);
        return  !buffer.hasRemaining();
    }*/
}
